From: Keir Fraser Date: Thu, 28 May 2009 08:51:43 +0000 (+0100) Subject: x86 vmx: Unrestricted guest (realmode) support X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13861 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=115e860529f9823cbcb7383555794cdf8a8a67cd;p=xen.git x86 vmx: Unrestricted guest (realmode) support It allows fully virtualized guests to run real mode and unpaged mode code natively in the VMX mode when EPT is turned on. With the unrestricted guest there is no need to emulate the guest real mode code in the vm86 container or in the emulator. Also the guest big real mode code works like native. This patch enhances Xen to use the unrestricted guest feature if available on the processor. It also adds a new xen parameter to disable the unrestricted guest feature at the boot time. Signed-off-by: Nitin A Kamble --- diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 400d31de74..881a9a832b 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -41,6 +41,9 @@ static int opt_vpid_enabled = 1; boolean_param("vpid", opt_vpid_enabled); +static int opt_unrestricted_guest_enabled = 1; +boolean_param("unrestricted_guest", opt_unrestricted_guest_enabled); + /* Dynamic (run-time adjusted) execution control flags. */ u32 vmx_pin_based_exec_control __read_mostly; u32 vmx_cpu_based_exec_control __read_mostly; @@ -68,6 +71,7 @@ static void __init vmx_display_features(void) P(cpu_has_vmx_vpid, "Virtual-Processor Identifiers (VPID)"); P(cpu_has_vmx_vnmi, "Virtual NMI"); P(cpu_has_vmx_msr_bitmap, "MSR direct-access bitmap"); + P(cpu_has_vmx_unrestricted_guest, "Unrestricted Guest"); #undef P if ( !printed ) @@ -139,6 +143,9 @@ static void vmx_init_vmcs_config(void) SECONDARY_EXEC_ENABLE_EPT); if ( opt_vpid_enabled ) opt |= SECONDARY_EXEC_ENABLE_VPID; + if ( opt_unrestricted_guest_enabled ) + opt |= SECONDARY_EXEC_UNRESTRICTED_GUEST; + _vmx_secondary_exec_control = adjust_vmx_controls( min, opt, MSR_IA32_VMX_PROCBASED_CTLS2); } @@ -156,7 +163,9 @@ static void vmx_init_vmcs_config(void) if ( must_be_one & (CPU_BASED_INVLPG_EXITING | CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING) ) - _vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; + _vmx_secondary_exec_control &= + ~(SECONDARY_EXEC_ENABLE_EPT | + SECONDARY_EXEC_UNRESTRICTED_GUEST); } #if defined(__i386__) @@ -532,7 +541,9 @@ static int construct_vmcs(struct vcpu *v) } else { - v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; + v->arch.hvm_vmx.secondary_exec_control &= + ~(SECONDARY_EXEC_ENABLE_EPT | + SECONDARY_EXEC_UNRESTRICTED_GUEST); vmx_vmexit_control &= ~(VM_EXIT_SAVE_GUEST_PAT | VM_EXIT_LOAD_HOST_PAT); vmx_vmentry_control &= ~VM_ENTRY_LOAD_GUEST_PAT; diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index dddd9ec108..e256f51de6 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1062,8 +1062,10 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr) { case 0: { int realmode; - unsigned long hw_cr0_mask = - X86_CR0_NE | X86_CR0_PG | X86_CR0_PE; + unsigned long hw_cr0_mask = X86_CR0_NE; + + if ( !vmx_unrestricted_guest(v) ) + hw_cr0_mask |= X86_CR0_PG | X86_CR0_PE; if ( paging_mode_shadow(v->domain) ) hw_cr0_mask |= X86_CR0_WP; @@ -1091,7 +1093,9 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr) } realmode = !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE); - if ( realmode != v->arch.hvm_vmx.vmx_realmode ) + + if ( (!vmx_unrestricted_guest(v)) && + (realmode != v->arch.hvm_vmx.vmx_realmode) ) { enum x86_segment s; struct segment_register reg[x86_seg_tr + 1]; @@ -1431,15 +1435,10 @@ void start_vmx(void) } if ( cpu_has_vmx_ept ) - { - printk("VMX: EPT is available.\n"); vmx_function_table.hap_supported = 1; - } if ( cpu_has_vmx_vpid ) { - printk("VMX: VPID is available.\n"); - vpid_bitmap = xmalloc_array( unsigned long, BITS_TO_LONGS(VPID_BITMAP_SIZE)); BUG_ON(vpid_bitmap == NULL); diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index 80640e0d5a..c2b468e664 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -170,6 +170,7 @@ extern u32 vmx_vmentry_control; #define SECONDARY_EXEC_ENABLE_EPT 0x00000002 #define SECONDARY_EXEC_ENABLE_VPID 0x00000020 #define SECONDARY_EXEC_WBINVD_EXITING 0x00000040 +#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080 extern u32 vmx_secondary_exec_control; extern bool_t cpu_has_vmx_ins_outs_instr_info; @@ -194,6 +195,11 @@ extern bool_t cpu_has_vmx_ins_outs_instr_info; (vmx_cpu_based_exec_control & CPU_BASED_MONITOR_TRAP_FLAG) #define cpu_has_vmx_pat \ (vmx_vmentry_control & VM_ENTRY_LOAD_GUEST_PAT) +#define cpu_has_vmx_unrestricted_guest \ + (vmx_secondary_exec_control & SECONDARY_EXEC_UNRESTRICTED_GUEST) +#define vmx_unrestricted_guest(v) \ + ((v)->arch.hvm_vmx.secondary_exec_control & \ + SECONDARY_EXEC_UNRESTRICTED_GUEST) /* GUEST_INTERRUPTIBILITY_INFO flags. */ #define VMX_INTR_SHADOW_STI 0x00000001